package com.sojson.service.impl;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sojson.config.exception.TransException;
import com.sojson.constant.ConstantMessageSystemTemplate;
import com.sojson.constant.Lock;
import com.sojson.dao.CommentDao;
import com.sojson.dao.HotelDao;
import com.sojson.dao.HotelOrderDao;
import com.sojson.dao.HotelOrderRoomDao;
import com.sojson.dao.HotelRoomDao;
import com.sojson.dao.MemberDao;
import com.sojson.dao.OrderDao;
import com.sojson.dao.SpecsAttrDao;
import com.sojson.entity.po.Comment;
import com.sojson.entity.po.Hotel;
import com.sojson.entity.po.HotelOrder;
import com.sojson.entity.po.HotelOrderRoom;
import com.sojson.entity.po.HotelRoom;
import com.sojson.entity.po.Member;
import com.sojson.entity.po.Order;
import com.sojson.entity.po.OrderGoods;
import com.sojson.entity.vo.CommentVo;
import com.sojson.enums.EMessageSystemType;
import com.sojson.enums.EOrderStatusHotel;
import com.sojson.enums.core.EAuditStatus;
import com.sojson.enums.core.EModuleNo;
import com.sojson.enums.core.EOrderStatus;
import com.sojson.service.CommentService;
import com.sojson.service.MessageSystemService;
import com.sojson.service.OrderGoodsService;
import com.sojson.util.ArithUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.file.FileDepotUtil;
import com.sojson.util.file.constant.ConstantFileFieldName;
import com.sojson.util.file.enums.EFileTable;
import com.sojson.util.token.Token;
import com.sojson.util.token.TokenUtil;

/**
 * 商品评论表Service实现类
 * 
 * @author liu
 * @date 2021-03-16
 */
@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private MessageSystemService messageSystemService;
    @Autowired
    private OrderGoodsService orderGoodsService;
    @Resource
    private CommentDao commentDaoImpl;
    @Resource
    private OrderDao orderDaoImpl;
    @Resource
    private HotelDao hotelDaoImpl;
    @Resource
    private HotelRoomDao hotelRoomDaoImpl;
    @Resource
    private HotelOrderDao hotelOrderDaoImpl;
    @Resource
    private HotelOrderRoomDao hotelOrderRoomDaoImpl;
    @Resource
    private SpecsAttrDao specsAttrDaoImpl;
    @Resource
    private MemberDao memberDaoImpl;

    /**
     * 单条插入
     * 
     * @param comment
     * @return
     * @throws Exception 
     */
    @Override
    @Transactional
    public int insert(Comment comment) throws Exception {
        // 获取当前登录的用户
        Token token = TokenUtil.getToken();
        Member member = token.getMember();
        Integer id = member.getId();
        String no = member.getNo();

        // 查询订单
        Order findById = orderDaoImpl.findById(comment.getOrderId());
        // 检查订单是否正确
        if (StringUtil.isBlankObject(findById)) {
            throw new TransException("订单不存在！");
        }
        if (!findById.getUserNo().equals(no)) {
            throw new TransException("订单不是此帐号的！");
        }
        if (findById.getStatus() != EOrderStatus.COMMENT_NO.getCode()
            && findById.getStatus() != EOrderStatus.RETU_YES.getCode()) {
            throw new TransException("订单未完成！");
        }
        StringBuilder stringBuilder = new StringBuilder();
        OrderGoods orderGoods = new OrderGoods();
        orderGoods.setOrderNo(findById.getNo());
        List<OrderGoods> findByDto = orderGoodsService.findByDto(orderGoods);
        if (StringUtil.isBlankObject(findByDto) || findByDto.size() < 1) {
            throw new TransException("商品规格信息不存在！");
        }
        for (OrderGoods og : findByDto) {
            stringBuilder.append(og.getGoodName());
            stringBuilder.append(":");
            stringBuilder.append(og.getSpecsName());
            stringBuilder.append(" ");
        }

        // 获取规格详细信息
        comment.setNickName(member.getNickName());
        comment.setHeadImg(member.getHeadImg());
        comment.setMerchantNo(findById.getMerchantNo());
        comment.setMid(id);
        comment.setGoodId(findById.getGoodId());
        comment.setGoodSpecsId(findById.getGoodSpecsId());
        comment.setOrderId(findById.getId());
        comment.setSpecsName(stringBuilder.toString());
        int insert = commentDaoImpl.insert(comment);
        if (insert < 1) {
            throw new TransException("评价失败，请重试！");
        }

        FileDepotUtil.insertListSync(EFileTable.COMMENT, ConstantFileFieldName.IMAGES, comment.getImages());

        // 修改订单状态
        Order order = new Order();
        order.updateInit();
        order.setId(findById.getId());
        order.setStatus(EOrderStatus.RETU_YES.getCode());
        orderDaoImpl.updatePartialById(order);

        Member findByNo = memberDaoImpl.findByNo(findById.getMerchantNo());
        if (StringUtil.isBlankObject(findByNo)) {
            return insert;
        }
        // 发送消息
        messageSystemService.send(
            ConstantMessageSystemTemplate.getOrder(findById, findByDto, ConstantMessageSystemTemplate.ORDER_COMMENT),
            EMessageSystemType.ORDER.getCode(), Integer.valueOf(EModuleNo.SHOPPING_MALL.getCode()),
            findById.getId() + "", findByNo);
        return insert;
    }

    /**
     * 单条插入
     * 
     * @param comment
     * @return
     * @throws Exception 
     */
    @Override
    @Transactional
    public int insertHotel(Comment comment) throws Exception {
        // 获取当前登录的用户
        Token token = TokenUtil.getToken();
        Integer id = token.getMember().getId();
        String no = token.getMember().getNo();

        // 查询订单
        HotelOrder findById = hotelOrderDaoImpl.findById(comment.getOrderId());
        // 检查订单是否正确
        if (StringUtil.isBlankObject(findById)) {
            throw new TransException("订单不存在！");
        }
        if (!findById.getNoUser().equals(no)) {
            throw new TransException("订单不是此帐号的！");
        }
        if (findById.getStatus() != EOrderStatusHotel.COMMENT_NO.getCode()
            && findById.getStatus() != EOrderStatusHotel.RETU_YES.getCode()) {
            throw new TransException("订单未完成！");
        }
        HotelOrderRoom findByNoHotelOrder = hotelOrderRoomDaoImpl.findByNoHotelOrder(findById.getNo());
        HotelRoom room = hotelRoomDaoImpl.findByNo(findById.getNoRoom());
        Hotel hotel = null;
        if (StringUtil.isNotBlankObject(room)) {
            hotel = hotelDaoImpl.findByNo(room.getNoHotel());
        }

        // 获取规格详细信息
        comment.setMerchantNo(findById.getNoMerchant());
        comment.setMid(id);
        comment.setGoodId(StringUtil.isNotBlankObject(hotel) ? hotel.getId() : null);
        comment.setGoodSpecsId(StringUtil.isNotBlankObject(room) ? room.getId() : null);
        comment.setOrderId(findById.getId());
        comment.setSpecsName(findByNoHotelOrder.getNameHotel() + "-" + findByNoHotelOrder.getNameRoom());
        int insert = commentDaoImpl.insert(comment);
        if (insert < 1) {
            throw new TransException("评价失败，请重试！");
        }

        FileDepotUtil.insertListSync(EFileTable.COMMENT, ConstantFileFieldName.IMAGES, comment.getImages());

        // 修改订单状态
        HotelOrder order = new HotelOrder();
        order.updateInit();
        order.setId(findById.getId());
        order.setStatus(EOrderStatusHotel.RETU_YES.getCode());
        hotelOrderDaoImpl.updateById(order);

        Member findByNo = memberDaoImpl.findByNo(findById.getNoMerchant());
        if (StringUtil.isBlankObject(findByNo)) {
            return insert;
        }
        // 发送消息
        messageSystemService.send(
            ConstantMessageSystemTemplate.getOrder(findById, findByNoHotelOrder,
                ConstantMessageSystemTemplate.ORDER_COMMENT),
            EMessageSystemType.ORDER.getCode(), Integer.valueOf(EModuleNo.HOTEL.getCode()), findById.getNo(), findByNo);
        return insert;
    }

    /**
     * 批量插入
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public int insertList(Comment comment) {
        int insertList = commentDaoImpl.insertList(comment.getComments());
        return insertList;
    }

    /**
     * 通过对象批量删除(物理删除)
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public int deleteByDto(Comment comment) {
        int deleteByDto = commentDaoImpl.deleteByDto(comment);
        return deleteByDto;
    }

    /**
     * 统计全部数量
     * 
     * @return
     * @throws SQLException
     */
    @Override
    public int countAll() {
        int countAll = commentDaoImpl.countAll();
        return countAll;
    }

    /**
     * 查询所有
     * 
     * @return
     * @throws SQLException
     */
    @Override
    public List<Comment> findAll() {
        List<Comment> findAll = commentDaoImpl.listAll();
        return findAll;
    }

    /**
     * 根据对象统计数量
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public int countByDto(Comment comment) {
        int countByDto = commentDaoImpl.countByDto(comment);
        return countByDto;
    }

    /**
     * 根据对象查询
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public List<Comment> findByDto(Comment comment) {
        List<Comment> findByDto = commentDaoImpl.listByDto(comment);
        return findByDto;
    }

    /**
     * 通过id删除(物理删除)
     * 
     * @param id
     * @return
     * @throws SQLException
     */
    @Override
    public int deleteById(Integer id) {
        int deleteById = commentDaoImpl.deleteById(id);
        return deleteById;
    }

    /**
     * 通过id列表删除(物理删除)
     * 
     * @param ids
     * @return
     * @throws SQLException
     */
    @Override
    public int deleteByIdList(ArrayList<Integer> ids) {
        int deleteByIdList = commentDaoImpl.deleteByIdList(ids);
        return deleteByIdList;
    }

    /**
     * 通过id更新(全部更新)
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public int updateById(Comment comment) {
        int updateById = commentDaoImpl.updateById(comment);
        return updateById;
    }

    /**
     * 通过id列表更新(全部更新)(更新内容相同)
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public int updateStaticByIdList(Comment comment) {
        int updateStaticByIdList = commentDaoImpl.updateStaticByIdList(comment);
        return updateStaticByIdList;
    }

    /**
     * 通过id列表更新(全部更新)(更新内容不相同)
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public int updateChangeByIdList(Comment comment) {
        int updateChangeByIdList = commentDaoImpl.updateChangeByIdList(comment.getComments());
        return updateChangeByIdList;
    }

    /**
     * 通过id更新(局部更新)
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public int updatePartialById(Comment comment) {
        int updatePartialById = commentDaoImpl.updatePartialById(comment);
        return updatePartialById;
    }

    /**
     * 通过id列表更新(局部更新)(更新内容相同)
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public int updateStaticPartialByIdList(Comment comment) {
        int updateStaticPartialByIdList = commentDaoImpl.updateStaticPartialByIdList(comment);
        return updateStaticPartialByIdList;
    }

    /**
     * 通过id列表更新(局部更新)(更新内容不相同)
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public int updateChangePartialByIdList(Comment comment) {
        int updateChangePartialByIdList = commentDaoImpl.updateChangePartialByIdList(comment.getComments());
        return updateChangePartialByIdList;
    }

    /**
     * 通过id查询
     * 
     * @param id
     * @return
     * @throws SQLException
     */
    @Override
    public Comment findById(Integer id) {
        Comment findById = commentDaoImpl.findById(id);
        return findById;
    }

    /**
     * 通过id列表查询
     * 
     * @param ids
     * @return
     * @throws SQLException
     */
    @Override
    public ArrayList<Comment> findByIdList(ArrayList<Integer> ids) {
        ArrayList<Comment> findByIdList = commentDaoImpl.findByIdList(ids);
        return findByIdList;
    }

    /**
     * 通过对象查询id列表
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public ArrayList<Integer> findIdByDto(Comment comment) {
        ArrayList<Integer> findIdByDto = commentDaoImpl.findIdByDto(comment);
        return findIdByDto;
    }

    /**
     * 清空数据(物理清空)
     * 
     * @throws SQLException
     */
    @Override
    public void clear() {
        commentDaoImpl.clear();
    }

    /**
     * 审核评论信息
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    @Transactional
    public int audit(Comment comment) {
        int updatePartialById = 0;
        // 好评数量
        int count = 0;
        synchronized (Lock.COMMENT_COUNT) {
            Comment findById = commentDaoImpl.findById(comment.getId());
            if (findById.getStatus() != EAuditStatus.AUDITING.getCode()) {
                throw new TransException("评论已审核！");
            }
            Float starNum = findById.getStarNum();
            if (starNum > 3) {
                count = 1;
            }

            Comment comm = new Comment();
            comm.setId(comment.getId());
            comm.setStatus(comment.getStatus());
            updatePartialById = commentDaoImpl.updatePartialById(comm);

            if (comment.getStatus() == EAuditStatus.SUCCESS.getCode()) {
                if (EModuleNo.SHOPPING_MALL.getCode().equals(findById.getNoModule())) {
                    // 获取店铺当前星级
                    Member findByGoodsId = memberDaoImpl.findMerchantByOrderId(findById.getOrderId());
                    if (StringUtil.isBlankObject(findByGoodsId)) {
                        return 0;
                    }

                    // 修改店铺星级
                    Member member = new Member();
                    member.setId(findByGoodsId.getId());
                    member.setCommentCount(findByGoodsId.getCommentCount() + 1);
                    member.setCommentCountStarLevel(
                        findByGoodsId.getCommentCountStarLevel().add(new BigDecimal(starNum)));
                    member.setCommentGoodCount(findByGoodsId.getCommentGoodCount() + count);
                    BigDecimal divRoundDown = ArithUtil.divRoundDown(member.getCommentCountStarLevel(),
                        new BigDecimal(member.getCommentCount()), 1);
                    member.setStarLevelStore(divRoundDown.floatValue());
                    updatePartialById = memberDaoImpl.updatePartialById(member);
                } else if (EModuleNo.HOTEL.getCode().equals(findById.getNoModule())) {
                }
            }
        }

        return updatePartialById;
    }

    /**
     * 根据对象查询(包含其他附加内容)
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public List<CommentVo> list(Comment comment) {
        return commentDaoImpl.list(comment);
    }

    /**
     * 根据对象查询(包含其他附加内容)
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public List<CommentVo> arrayGoods(CommentVo comment) {
        return commentDaoImpl.arrayGoods(comment);
    }

    /**
     * 根据对象查询(包含其他附加内容)
     * 
     * @param comment
     * @return
     * @throws SQLException
     */
    @Override
    public List<CommentVo> arrayHotel(CommentVo comment) {
        return commentDaoImpl.arrayHotel(comment);
    }

    /**
     * 通过id查询(包含其他附加内容)
     * 
     * @param id
     * @return
     * @throws SQLException
     */
    @Override
    public CommentVo getInfo(Integer id) {
        return commentDaoImpl.getInfo(id);
    }

    /**
     * 通过id查询(包含其他附加内容)
     * 
     * @param id
     * @return
     * @throws SQLException
     */
    @Override
    public CommentVo getMsg(Integer id) {
        return commentDaoImpl.getMsg(id);
    }

}